﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;

namespace Hostblock
{
    public partial class Mainform : Form
    {
        private bool asave;
        private bool ChangesDone;
        private string HostPathWoW = Environment.GetFolderPath(Environment.SpecialFolder.SystemX86) + @"\drivers\etc\hosts";
        private string HostsPath = Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\drivers\etc\hosts";
        private bool x64;

        public Mainform()
        {
            InitializeComponent();
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            Searchbar.Visible = false;
        }

        private void button1_Click_2(object sender, EventArgs e)
        {
            ShowMainWindow();
        }

        private void button1_Click_3(object sender, EventArgs e)
        {
            ShowMainWindow();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Preview();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            HostAdd(UrlBox.Text);
        }

        private void button6_Click(object sender, EventArgs e)
        {
            ShowMainWindow();
        }

        private void ButtonAbout_Click(object sender, EventArgs e)
        {
            HideAllDialogs();
            PanelAbout.Visible = true;
        }

        private void ButtonAbout_Click_1(object sender, EventArgs e)
        {
            HideAllDialogs();
            PanelAbout.Visible = true;
        }

        private void ButtonAdd_Click(object sender, EventArgs e)
        {
            OpenAddDialog();
        }

        private void ButtonDelete_Click(object sender, EventArgs e)
        {
            DeleteHost();
        }

        private void ButtonExport_Click(object sender, EventArgs e)
        {
            if (ExportFileDialog.ShowDialog() == DialogResult.OK)
            {
                Export(ExportFileDialog.FileName);
            }
        }

        private void ButtonExport_Click_1(object sender, EventArgs e)
        {
            if (ExportFileDialog.ShowDialog() == DialogResult.OK)
            {
                ShowMainWindow();
                Export(ExportFileDialog.FileName);
            }
        }

        private void ButtonImport_Click(object sender, EventArgs e)
        {
            if (ImportFileDialog.ShowDialog() == DialogResult.OK)
                Import(ImportFileDialog.FileName);
        }

        private void ButtonImport_Click_1(object sender, EventArgs e)
        {
            if (ImportFileDialog.ShowDialog() == DialogResult.OK)
            {
                ShowMainWindow();
                Import(ImportFileDialog.FileName);
            }
        }

        private void ButtonOpen_Click(object sender, EventArgs e)
        {
            LoadHostsList();
        }

        private void ButtonWipe_Click(object sender, EventArgs e)
        {
            WipeList();
        }

        private void ButtonWipe_Click_1(object sender, EventArgs e)
        {
            ShowMainWindow();
            WipeList();
        }

        private void CacheList_SelectedIndexChanged(object sender, EventArgs e)
        {
        }

        private void DeleteHost()
        {
            ShowMainWindow();
            int i = BlockList.SelectedIndex;
            if (i != -1)
            {
                LastActionResult.Text = @"Host " + BlockList.Items[i] + @" deleted";
                BlockList.Items.RemoveAt(i);
                UnsavedChanges(true);
                if (BlockList.Items.Count > 0)
                {
                    try
                    {
                        BlockList.SelectedIndex = i;
                    }
                    catch (Exception)
                    {
                        BlockList.SelectedIndex = i - 1;
                    }
                }
                else
                {
                    BlockList.SelectedIndex = -1;
                }
            }
            else
            {
                LastActionResult.Text = @"Can not delete, no host selected";
            }
        }

        private void Export(string ding)
        {
            ShowMainWindow();
            FileList.Items.Clear();
            if (ding.EndsWith(@".hbf"))
            {
                for (int i = 0; i < BlockList.Items.Count; i++)
                {
                    FileList.Items.Add(BlockList.Items[i]);
                }
            }
            else if (ding.EndsWith(@".txt"))
            {
                for (int i = 0; i < BlockList.Items.Count; i++)
                {
                    FileList.Items.Add(BlockList.Items[i]);
                }
            }
            else if (ding.EndsWith(@".cmd"))
            {
                FileList.Items.Add(@"@echo off");
                FileList.Items.Add(@"echo. >>%windir%\system32\drivers\etc\HOSTS && goto suc");
                FileList.Items.Add(@"goto gottabeadmin");
                FileList.Items.Add(@":gottabeadmin");
                FileList.Items.Add(@"echo You have to start the import with administrative privileges");
                FileList.Items.Add(@"pause");
                FileList.Items.Add(@"goto end");
                FileList.Items.Add(@":suc");
                for (int i = 0; i < BlockList.Items.Count; i++)
                {
                    FileList.Items.Add(@"echo 127.0.0.1 " + BlockList.Items[i] + @">>%windir%\system32\drivers\etc\HOSTS");
                }
                FileList.Items.Add(@":end");
            }
            else if (ding.EndsWith(@".tpl"))
            {
                FileList.Items.Add(@"msFilterList");
                FileList.Items.Add(@": Expires=5");
                for (int i = 0; i < BlockList.Items.Count; i++)
                {
                    FileList.Items.Add(@"-d " + BlockList.Items[i]);
                }
            }
            if (SaveToFile(ding, FileList))
            {
                LastActionResult.Text = @"Block list exported to " + ding;
            }
        }

        private string GetHost(string URL)
        {
            int i = URL.IndexOf(@"/");
            return URL.Remove(i);
        }

        private void HideAllDialogs()
        {
            UrlBox.Text = null;
            if (Convert.ToString(webBrowser1.Url) != @"about:blank")
            {
                webBrowser1.Url = null;
            }
            Searchbar.Visible = false;
            PanelMain.Visible = false;
            PanelAdd.Visible = false;
            PanelSettings.Visible = false;
            PanelAbout.Visible = false;
        }

        private void HostAdd(string ding)
        {
            ding = ParseIt(ding);
            if (IsJS(ding))
            {
                LastActionResult.Text = ding + @" is Javascript target and can not be blocked";
            }
            else if (IsIP(ding))
            {
                LastActionResult.Text = ding + @" is an IP address and can not be blocked";
            }
            else if (IsLH(ding))
            {
                LastActionResult.Text = ding + @" is not an internet address and can not be blocked";
            }
            else if (IsUndef(ding))
            {
                LastActionResult.Text = ding + @" is not an internet address and can not be blocked";
            }
            else
            {
                Search(ding);
                if (BlockList.SelectedIndex == -1)
                {
                    BlockList.Items.Add(ding);
                    LastActionResult.Text = @"Host " + ding + @" added";
                    UnsavedChanges(true);
                }
                else
                {
                    LastActionResult.Text = @"Host " + ding + @" already blocked";
                }
                UrlBox.Text = null;
            }
        }

        private void Import(string Dateiname)
        {
            int amount = 0;
            int oldamount = BlockList.Items.Count;
            ShowMainWindow();
            FileList.Items.Clear();
            if (ReadFromFile(Dateiname, FileList))
            {
                for (int i = 0; i < FileList.Items.Count; i++)
                {
                    HostAdd(Convert.ToString(FileList.Items[i]));
                }
                if (asave)
                {
                    SaveHostsList();
                    Application.Exit();
                }
                amount = BlockList.Items.Count - oldamount;
                if (amount > 0)
                {
                    LastActionResult.Text = Convert.ToString(amount) + @" hosts imported from " + Dateiname;
                    UnsavedChanges(true);
                    if (MessageBox.Show(LastActionResult.Text + @". Save block list now?", @"Hostblock", MessageBoxButtons.YesNo) == DialogResult.Yes)
                    {
                        SaveHostsList();
                    }
                }
                else
                {
                    LastActionResult.Text = @"No hosts imported from " + Dateiname;
                }
            }
        }

        private bool IsIP(string URL)
        {
            bool IP = true;
            for (int i = 0; i < 25; i++)
            {
                if (URL.Contains(Convert.ToString(LetterList.Items[i])))
                {
                    IP = false;
                }
            }
            return IP;
        }

        private bool IsJS(string URL)
        {
            URL = URL.ToLowerInvariant();
            if (URL.StartsWith(@"javascript:"))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private bool IsLH(string URL)
        {
            URL = URL.ToLowerInvariant();
            if (URL.StartsWith(@"localhost"))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private bool IsUndef(string URL)
        {
            URL = URL.ToLowerInvariant();
            if (URL.StartsWith(@"undefined"))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private void label1_Click(object sender, EventArgs e)
        {
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process.Start(@"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UH64QFB6R85M2");
        }

        private void LoadHostsList()
        {
            ShowMainWindow();
            FileList.Items.Clear();
            CacheList.Items.Clear();
            BlockList.Items.Clear();
            if (ReadFromFile(HostsPath, FileList))
            {
                CacheList.BeginUpdate();
                BlockList.BeginUpdate();
                for (int i = 0; i < FileList.Items.Count; i++)
                {
                    string ding = Convert.ToString(FileList.Items[i]);
                    if (ding.StartsWith(@"127.0.0.1"))
                    {
                        if (ding.Contains(@"localhost"))
                        {
                            CacheList.Items.Add(ding);
                        }
                        else
                        {
                            ding = ding.Remove(0, 9);
                            ding = ding.Trim();
                            BlockList.Items.Add(ding);
                        }
                    }
                    else
                    {
                        CacheList.Items.Add(ding);
                    }
                }
                BlockList.EndUpdate();
                CacheList.EndUpdate();
                FileList.Items.Clear();
                UnsavedChanges(false);
                LastActionResult.Text = @"Block list loaded";
            }
        }

        private void Mainform_FormClosing(object sender, FormClosingEventArgs e)
        {
            if ((ChangesDone) & (!asave))
            {
                DialogResult qresult = MessageBox.Show(@"Unsaved changes, do you want to save?", @"Hostblock", MessageBoxButtons.YesNoCancel);
                if (qresult == DialogResult.Yes)
                {
                    asave = true;
                    SaveHostsList();
                }
                else if (qresult == DialogResult.No)
                {
                }
                else if (qresult == DialogResult.Cancel)
                {
                    e.Cancel = true;
                }
            }
        }

        private void Mainform_Load(object sender, EventArgs e)
        {
        }

        private void Mainform_Shown(object sender, EventArgs e)
        {
            PanelMain.Dock = DockStyle.Fill;
            PanelAdd.Dock = DockStyle.Fill;
            PanelSettings.Dock = DockStyle.Fill;
            PanelAbout.Dock = DockStyle.Fill;
            x64 = Environment.Is64BitOperatingSystem;
            //ButtonSave.Image = SystemIcons.Shield.ToBitmap();
            LoadHostsList();
            string[] arguments = Environment.GetCommandLineArgs();
            if (arguments.Length > 1)
            {
                string parm = arguments[1];
                if (File.Exists(parm))
                {
                    if (arguments.Length > 2)
                    {
                        string autosave = arguments[2].ToLowerInvariant();
                        if (autosave.Contains("autosave"))
                        {
                            asave = true;
                        }
                        else
                        {
                            asave = false;
                        }
                    }
                    Import(parm);
                }
                else
                {
                    OpenAddDialog();
                    UrlBox.Text = parm;
                    Preview();
                }
            }
            else
            {
                if (BlockList.Items.Count == 0)
                {
                    if (MessageBox.Show(@"Empty block list. To block ads with Hostblock, you need a block list. Do you want to download one now?", "Hostblock", MessageBoxButtons.YesNo) == DialogResult.Yes)
                    {
                        Process.Start(@"http://hostblock.codeplex.com/releases/view/92678");
                    }
                }
            }
        }

        private void OpenAddDialog()
        {
            HideAllDialogs();
            PanelAdd.Visible = true;
            UrlBox.Focus();
        }

        private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
        }

        private void OpenSearchDialog()
        {
            HideAllDialogs();
            PanelMain.Visible = true;
            Searchbar.Visible = true;
            SearchBox.Text = null;
            SearchBox.Focus();
        }

        private string ParseIt(string URL)
        {
            if (URL.StartsWith(@"http://"))
            {
                URL = URL.Remove(0, 7);
            }
            if (URL.StartsWith(@"https://"))
            {
                URL = URL.Remove(0, 8);
            }
            if (URL.Contains(@"/"))
            {
                URL = GetHost(URL);
            }
            return URL;
        }

        private void Preview()
        {
            string ding = UrlBox.Text;
            ding = ParseIt(ding);
            if (IsJS(ding))
            {
                LastActionResult.Text = ding + @" is Javascript target and can not be blocked";
            }
            else if (IsIP(ding))
            {
                LastActionResult.Text = ding + @" is an IP address and can not be blocked";
            }
            else if (IsLH(ding))
            {
                LastActionResult.Text = ding + @" is not an internet address and can not be blocked";
            }
            else if (IsUndef(ding))
            {
                LastActionResult.Text = ding + @" is not an internet address and can not be blocked";
            }
            else
            {
                webBrowser1.Navigate(ding);
                button2.Enabled = false;
                LastActionResult.Text = @"Previewing " + ding;
            }
        }

        private bool ReadFromFile(string FileName, ListBox ListToWrite)
        {
            try
            {
                ListToWrite.BeginUpdate();
                ListToWrite.Items.Clear();
                StreamReader read = new StreamReader(FileName);
                String ext = (Path.GetExtension(FileName));
                while (read.Peek() >= 0)
                    if (!(ext == @".tpl"))
                        ListToWrite.Items.Add(Convert.ToString(read.ReadLine()));
                    else if (ext == @".tpl")
                    {
                        string temp = read.ReadLine();
                        if (temp.StartsWith(@"-d "))
                        {
                            temp = temp.Remove(0, 3);
                            if (!(temp.Contains(" ")))
                                ListToWrite.Items.Add(temp);
                        }
                    }
                ListToWrite.EndUpdate();
                return (true);
            }
            catch (Exception ex)
            {
                LastActionResult.Text = (Convert.ToString(ex.Message));
                ListToWrite.EndUpdate();
                return (false);
            }
        }

        private void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
        }

        private void SaveHostsList()
        {
            ShowMainWindow();
            FileList.Items.Clear();
            for (int i = 0; i < CacheList.Items.Count; i++)
            {
                FileList.Items.Add(CacheList.Items[i]);
            }
            for (int i = 0; i < BlockList.Items.Count; i++)
            {
                FileList.Items.Add(@"127.0.0.1 " + BlockList.Items[i]);
            }
            bool NoHelper = false;
            if (SaveToFile(Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments) + @"\hosts", FileList))
            {
                String HelperPath = String.Empty;
                String HelperPath1 = @"Hostblock helper.exe";
                String HelperPath2 = @"..\..\..\Hostblock helper\bin\Release\" + HelperPath1;
                String HelperPath3 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Internet Explorer\Plugins\Hostblock\" + HelperPath1;
                String HelperPath4 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + @"\Internet Explorer\Plugins\Hostblock\" + HelperPath1;
                if (File.Exists(HelperPath1))
                    HelperPath = HelperPath1;
                else if (File.Exists(HelperPath2))
                    HelperPath = HelperPath2;
                else if (File.Exists(HelperPath3))
                    HelperPath = HelperPath3;
                else if (File.Exists(HelperPath4))
                    HelperPath = HelperPath4;
                else
                    NoHelper = true;
                if (!NoHelper)
                {
                    Process Helper = new Process();
                    Helper.StartInfo.FileName = HelperPath;
                    Helper.Start();
                    Helper.WaitForExit();
                    string rv = Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments) + @"\Hostblock";
                    if (File.Exists(rv))
                    {
                        string Ergebnis = File.ReadAllText(rv);
                        if (Ergebnis == "SUCCESS")
                        {
                            UnsavedChanges(false);
                            LastActionResult.Text = @"Block list saved";
                        }
                        else
                            LastActionResult.Text = Ergebnis;
                        File.Delete(rv);
                    }
                    else
                        NoHelper = true;
                }
            }
            if (NoHelper)
            {
                File.Delete(Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments) + @"\hosts");
                if (SaveToFile(HostsPath, FileList))
                {
                    UnsavedChanges(false);
                    if (x64)
                    {
                        File.Copy(HostsPath, HostPathWoW, true);
                    }
                    LastActionResult.Text = @"Block list saved";
                }
            }
        }

        private bool SaveToFile(string FileName, ListBox ListToRead)
        {
            try
            {
                StreamWriter Write = new StreamWriter(FileName);
                for (int I = 0; I < ListToRead.Items.Count; I++)
                {
                    Write.WriteLine(Convert.ToString(ListToRead.Items[I]));
                }
                Write.Close();
                ListToRead.Items.Clear();
                return (true);
            }
            catch (Exception ex)
            {
                LastActionResult.Text = (Convert.ToString(ex.Message));
                if (asave)
                {
                    MessageBox.Show(Convert.ToString(ex.Message));
                }
                ListToRead.Items.Clear();
                return (false);
            }
        }

        private void Search(string ding)
        {
            bool found = false;
            BlockList.SelectedIndex = -1;
            for (int i = 0; i < BlockList.Items.Count; i++)
            {
                if (Convert.ToString(BlockList.Items[i]).StartsWith(ding))
                {
                    BlockList.SelectedIndex = i;
                    found = true;
                    break;
                }
            }
            if (found)
            {
                LastActionResult.Text = @"Host " + Convert.ToString(BlockList.Items[BlockList.SelectedIndex]) + @" found";
            }
            else if (found == false)
            {
                LastActionResult.Text = @"Host " + SearchBox.Text + @" not found";
            }
        }

        private void SearchBox_TextChanged(object sender, EventArgs e)
        {
            string ding = LastActionResult.Text;
            if (SearchBox.Text != @"")
            {
                Search(SearchBox.Text);
            }
            else
            {
                BlockList.SelectedIndex = -1;
                LastActionResult.Text = ding;
            }
        }

        private void searchToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Searchbar.Visible = true;
        }

        private void ShowMainWindow()
        {
            HideAllDialogs();
            PanelMain.Visible = true;
        }

        private void statusStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            SaveHostsList();
        }

        private void toolStripButton5_Click(object sender, EventArgs e)
        {
            OpenSearchDialog();
        }

        private void toolStripStatusLabel1_Click(object sender, EventArgs e)
        {
        }

        private void toolStripStatusLabel1_Click_1(object sender, EventArgs e)
        {
        }

        private void toolStripStatusLabel3_Click(object sender, EventArgs e)
        {
        }

        private void UnsavedChanges(bool changes)
        {
            ChangesDone = changes;
            ButtonOpen.Enabled = changes;
            ButtonSave.Enabled = changes;
            WriteStatusAmount();
        }

        private void UrlBox_TextChanged(object sender, EventArgs e)
        {
            if (UrlBox.Text.Trim() != @"")
            {
                button2.Enabled = true;
                button3.Enabled = true;
            }
            else
            {
                button2.Enabled = false;
                button3.Enabled = false;
            }
        }

        private void WipeList()
        {
            ShowMainWindow();
            if (BlockList.Items.Count > 0)
            {
                BlockList.Items.Clear();
                UnsavedChanges(true);
                LastActionResult.Text = @"Block list wiped";
            }
            else
            {
                LastActionResult.Text = @"Can not wipe an empty list";
            }
        }

        private void WriteStatusAmount()
        {
            String Titelappendix = " - Hostblock";
            String Titelappendix2 = "* - Hostblock";
            if (BlockList.Items.Count == 0)
            {
                this.Text = @"No hosts" + Titelappendix;
            }
            else if (BlockList.Items.Count == 1)
            {
                this.Text = @"One host" + Titelappendix;
            }
            else
            {
                this.Text = Convert.ToString(BlockList.Items.Count) + @" hosts" + Titelappendix;
            }
            if (ChangesDone)
                this.Text = this.Text.Replace(Titelappendix, Titelappendix2);
        }
    }
}